package com.smasher.core.encrypt.oneway;


import android.text.TextUtils;

import androidx.annotation.NonNull;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

/**
 * MD5 工具类
 * MD5（Message-Digest Algorithm 5）是一种广泛使用的散列函数
 */
public class MD5Util {

    /**
     * MD5
     *
     * @param string 加密字符串
     * @return 加密结果字符串
     * @see #md5(String, String)
     */
    public static String md5(@NonNull String string) {
        return TextUtils.isEmpty(string) ? "" : md5(string, "");
    }

    /**
     * MD5 (加盐)
     *
     * @param string 目标字符串
     * @param slat   加密盐值key
     * @return 加密结果字符串
     */
    public static String md5(@NonNull String string, String slat) {
        if (TextUtils.isEmpty(string)) {
            return "";
        }

        try {
            MessageDigest md5 = MessageDigest.getInstance("MD5");
            String input = slat == null ? string : string + slat;
            byte[] bytes = md5.digest(input.getBytes());
            StringBuilder sb = new StringBuilder();
            for (byte b : bytes) {
                sb.append(String.format("%02x", b));
            }
            return sb.toString();
        } catch (NoSuchAlgorithmException e) {
            throw new IllegalStateException("MD5 algorithm not available.", e);
        }
    }


    /**
     * MD5 (多次)
     *
     * @param string 目标字符串
     * @param times  重复加密次数
     * @return 加密结果字符串
     */
    public static String md5(@NonNull String string, int times) {
        if (TextUtils.isEmpty(string)) {
            return "";
        }

        String md5 = string;
        for (int i = 0; i < times; i++) {
            md5 = md5(md5);
        }
        return md5;
    }


    /**
     * MD5 (文件)
     * 可用于文件校验。
     *
     * @param file 目标文件
     * @return md5 数值
     */
    public static String md5(@NonNull File file) {
        if (!file.isFile() || !file.exists()) {
            throw new IllegalArgumentException("File does not exist or is not a regular file.");
        }

        try (FileInputStream in = new FileInputStream(file)) {
            MessageDigest digest = MessageDigest.getInstance("MD5");
            byte[] buffer = new byte[8192]; // 使用 8KB 缓冲区以提高读取效率
            int len;
            while ((len = in.read(buffer)) != -1) {
                digest.update(buffer, 0, len);
            }

            // 将字节数组转换为 BigInteger 并格式化为 32 位十六进制字符串
            byte[] hashBytes = digest.digest();
            BigInteger no = new BigInteger(1, hashBytes);
            return String.format("%032x", no);
        } catch (NoSuchAlgorithmException e) {
            throw new IllegalStateException("MD5 algorithm not available.", e);
        } catch (IOException e) {
            throw new RuntimeException("Failed to read file: " + e.getMessage(), e);
        }

    }
}
